#if 0

#include <windows.h>
#include <d2d1.h>
#include <mutex>
#include <atomic>

#include <stdio.h>
#include <conio.h>
#include <thread>
#include <chrono>
#include <vector>
#include "parsec-vdd.h"

#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "user32.lib")

#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p) = NULL; } }


using namespace std::chrono_literals;
using namespace parsec_vdd;


namespace {
    std::mutex g_animMutex;
    std::vector<DisplayAnimation> g_animations;
    std::atomic<bool> g_globalRunning(false);
}

// Direct2D动画线程函数
DWORD WINAPI AnimationThread(LPVOID lpParam) {
    DisplayAnimation* anim = static_cast<DisplayAnimation*>(lpParam);
    
    // 注册窗口类
    WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = DefWindowProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = "ParsecAnimClass";
    RegisterClassEx(&wc);

    // 创建透明窗口
    HWND hWnd = CreateWindowEx(
        WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
        "ParsecAnimClass", "",
        WS_POPUP,
        anim->rect.left,
        anim->rect.top,
        anim->rect.right - anim->rect.left,
        anim->rect.bottom - anim->rect.top,
        NULL, NULL, NULL, NULL);

    SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
    ShowWindow(hWnd, SW_SHOW);

    // 初始化Direct2D
    ID2D1Factory* pFactory = NULL;
    ID2D1HwndRenderTarget* pRT = NULL;
    ID2D1SolidColorBrush* pBrush = NULL;
    
    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);
    
    if (pFactory) {
        D2D1_SIZE_U size = D2D1::SizeU(
            anim->rect.right - anim->rect.left,
            anim->rect.bottom - anim->rect.top);
        
        pFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &pRT);
        
        if (pRT) {
            pRT->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White), &pBrush);
        }
    }

    // 动画循环
    float pos = 0.0f;
    const float speed = 2.0f;
    const float height = static_cast<float>(anim->rect.bottom - anim->rect.top);
    
    while (anim->active) {
        if (pRT && pBrush) {
            pRT->BeginDraw();
            pRT->Clear(D2D1::ColorF(0, 0, 0, 0));
            
            // 绘制移动线
            D2D1_RECT_F rect = D2D1::RectF(
                0, pos,
                static_cast<float>(anim->rect.right - anim->rect.left),
                pos + 2.0f);
            pRT->FillRectangle(rect, pBrush);
            
            pos += speed;
            if (pos > height) pos = 0;
            
            pRT->EndDraw();
        }
        Sleep(41); // ~25Hz, default 8, ~120Hz
    }

    // 清理资源
    SAFE_RELEASE(pBrush);
    SAFE_RELEASE(pRT);
    SAFE_RELEASE(pFactory);
    DestroyWindow(hWnd);
    delete anim;
    
    return 0;
}

BOOL parsec_vdd::StartDisplayAnimation(int index, const RECT& rect) {
    std::lock_guard<std::mutex> lock(g_animMutex);

    // 检查是否已存在
    for (const auto& anim : g_animations) {
        if (anim.index == index) return FALSE;
    }

    // 创建动画信息
    DisplayAnimation* newAnim = new DisplayAnimation;
    newAnim->index = index;
    newAnim->active = true;
    newAnim->rect = rect;

    // 启动线程
    newAnim->hThread = CreateThread(
        NULL, 0, AnimationThread, newAnim, 0, NULL);
    
    if (newAnim->hThread) {
        g_animations.push_back(*newAnim);
        return TRUE;
    }
    return FALSE;
}

void parsec_vdd::StopDisplayAnimation(int index) {
    std::lock_guard<std::mutex> lock(g_animMutex);

    for (auto it = g_animations.begin(); it != g_animations.end(); ++it) {
        if (it->index == index) {
            it->active = false;
            WaitForSingleObject(it->hThread, 1000);
            CloseHandle(it->hThread);
            g_animations.erase(it);
            break;
        }
    }
}


int main(int argc,char *argv[])
{
    // Check driver status.
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK)
    {
        printf("Parsec VDD device is not OK, got status %d.\n", status);
        return 1;
    }

    // Obtain device handle.
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("Failed to obtain the device handle.\n");
        return 1;
    }

    bool running = true;
    std::vector<int> displays;
    g_globalRunning = true;

    // Side thread for updating vdd.
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
    });

    updater.detach();

    // Print out guide.
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a add a virtual display at startup.\n");
    printf("\n");

    printf("Press A to add a virtual display.\n");
    printf("Press R to remove the last added.\n");
    printf("Press Q to quit (then unplug all).\n\n");

    if (running) {
        if (argc == 2 && strcmp(argv[1], "-a") == 0 ) {
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("Added a new virtual display, index: %d.\n", index);
            }
            else {
                printf("Limit exceeded (%d), could not add more virtual displays.\n", VDD_MAX_DISPLAYS);
            }
        }
    }

    // 修改后的用户交互循环
    while (running) {
        switch (_getch()) {
			// quit
            case 'q':
                running = false;
                break;
            // add display
        case 'a': {
            if (displays.size() >= VDD_MAX_DISPLAYS) {
                printf("Maximum displays reached\n");
                break;
            }

            int index = VddAddDisplay(vdd);
            if (index != -1) {
                displays.push_back(index);
                printf("Added display #%d\n", index);

                // 获取显示器信息
                DISPLAY_DEVICE dd = { sizeof(DISPLAY_DEVICE) };
                DEVMODE dm = { 0 };
                for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
                    if (strstr(dd.DeviceString, VDD_NAME_STRING) &&
                        EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) 
                    {
                        printf("Added DeviceString #%s\n", dd.DeviceString);
                        RECT rect = {
                            dm.dmPosition.x,
                            dm.dmPosition.y,
                            dm.dmPosition.x + dm.dmPelsWidth,
                            dm.dmPosition.y + dm.dmPelsHeight
                        };
                        StartDisplayAnimation(index, rect);
                        break;
                    }
                }
            }
            break;
        }
		 // remove display
        case 'r': {
            if (!displays.empty()) {
                int index = displays.back();
                StopDisplayAnimation(index);
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("Removed display #%d\n", index);
            }
            break;
        }
        // ... [其他case保持不变] ...
        }
    }

    // 退出时清理
    for (int index : displays) {
        StopDisplayAnimation(index);
        VddRemoveDisplay(vdd, index);
    }


#if 0
    while (running) {
        switch (_getch()) {
            // quit
            case 'q':
                running = false;
                break;
            // add display
            case 'a':
                if (displays.size() < VDD_MAX_DISPLAYS) {
                    int index = VddAddDisplay(vdd);
                    displays.push_back(index);
                    printf("Added a new virtual display, index: %d.\n", index);
                }
                else {
                    printf("Limit exceeded (%d), could not add more virtual displays.\n", VDD_MAX_DISPLAYS);
                }
                break;
            // remove display
            case 'r':
                if (displays.size() > 0) {
                    int index = displays.back();
                    VddRemoveDisplay(vdd, index);
                    displays.pop_back();
                    printf("Removed the last virtual display, index: %d.\n", index);
                }
                else {
                    printf("No added virtual displays.\n");
                }
                break;
        }
    }

    // Remove all before exiting.
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }
# endif

    if (updater.joinable()) {
        updater.join();
    }

    // Close the device handle.
    CloseDeviceHandle(vdd);

    return 0;
}


#endif

#if 0
#include <stdio.h>
#include <conio.h>
#include <thread>
#include <chrono>
#include <vector>
#include <Windows.h>
#include <d2d1.h>
#include "parsec-vdd.h"

#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "User32.lib")

using namespace std::chrono_literals;
using namespace parsec_vdd;

// 安全释放宏
#define SafeRelease(p) { if(p) { (p)->Release(); (p) = NULL; } }

// Direct2D相关全局变量
HWND g_hWnd = NULL;
ID2D1Factory* g_pD2DFactory = NULL;
ID2D1HwndRenderTarget* g_pRenderTarget = NULL;
ID2D1SolidColorBrush* g_pBrush = NULL;
RECT g_targetScreenRect = { 0 };
FLOAT g_fPosX = 0.0f;
bool g_animationRunning = false;

// 查找Parsec虚拟显示器
BOOL FindParsecDisplay(RECT& outRect)
{
    DISPLAY_DEVICE displayDevice = { 0 };
    displayDevice.cb = sizeof(DISPLAY_DEVICE);

    // 枚举所有显示器
    for (DWORD devNum = 0; EnumDisplayDevices(NULL, devNum, &displayDevice, 0); devNum++) {
        if (strstr(displayDevice.DeviceString, "Parsec Virtual Display")) {
            DEVMODE devMode = { 0 };
            devMode.dmSize = sizeof(DEVMODE);

            // 获取显示设置
            if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
                outRect.left = devMode.dmPosition.x;
                outRect.top = devMode.dmPosition.y;
                outRect.right = devMode.dmPosition.x + devMode.dmPelsWidth;
                outRect.bottom = devMode.dmPosition.y + devMode.dmPelsHeight;
                return TRUE;
            }
        }
    }
    return FALSE;
}

// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg) {
    case WM_CREATE: {
        // 初始化Direct2D
        if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory))) {
            return -1;
        }

        // 创建渲染目标
        D2D1_SIZE_U size = D2D1::SizeU(
            g_targetScreenRect.right - g_targetScreenRect.left,
            g_targetScreenRect.bottom - g_targetScreenRect.top
        );

        g_pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &g_pRenderTarget
        );

        // 创建画刷
        if (g_pRenderTarget) {
            g_pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White),
                &g_pBrush
            );
        }

        // 设置定时器（8ms ≈ 120Hz）
        SetTimer(hWnd, 1, 8, NULL);
        return 0;
    }

    case WM_TIMER: {
        if (!g_pRenderTarget || !g_animationRunning) break;

        const FLOAT screenWidth = static_cast<FLOAT>(g_targetScreenRect.right - g_targetScreenRect.left);
        const FLOAT screenHeight = static_cast<FLOAT>(g_targetScreenRect.bottom - g_targetScreenRect.top);

        g_pRenderTarget->BeginDraw();
        g_pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));  // 完全透明背景

        // 绘制移动白线（1像素高，全屏宽）
        D2D1_RECT_F rect = D2D1::RectF(0.0f, g_fPosX, screenWidth, g_fPosX + 1.0f);
        g_pRenderTarget->FillRectangle(&rect, g_pBrush);

        // 更新位置
        g_fPosX += 2.0f;
        if (g_fPosX > screenHeight) {
            g_fPosX = 0.0f;
            // 动画完成一个周期后停止
            g_animationRunning = false;
        }

        HRESULT hr = g_pRenderTarget->EndDraw();
        if (FAILED(hr)) {
            SafeRelease(g_pRenderTarget);
            SafeRelease(g_pBrush);
        }
        return 0;
    }

    case WM_DESTROY:
        KillTimer(hWnd, 1);
        SafeRelease(g_pBrush);
        SafeRelease(g_pRenderTarget);
        SafeRelease(g_pD2DFactory);
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}

// 注册窗口类
BOOL RegisterWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = "ParsecRefreshWindow";
    return RegisterClassEx(&wcex);
}

// 创建透明窗口
HWND CreateOverlayWindow(HINSTANCE hInstance) {
    if (!FindParsecDisplay(g_targetScreenRect)) {
        printf("未找到Parsec虚拟显示器\n");
        return NULL;
    }

    // 窗口样式设置
    DWORD dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST;
    DWORD dwStyle = WS_POPUP;

    // 创建覆盖整个目标屏幕的窗口
    HWND hWnd = CreateWindowEx(
        dwExStyle,
        "ParsecRefreshWindow",
        "Parsec Refresh Keeper",
        dwStyle,
        g_targetScreenRect.left,
        g_targetScreenRect.top,
        g_targetScreenRect.right - g_targetScreenRect.left,
        g_targetScreenRect.bottom - g_targetScreenRect.top,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hWnd) {
        SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
        ShowWindow(hWnd, SW_SHOWNOACTIVATE);
    }
    return hWnd;
}

// 启动屏幕刷新动画
void StartRefreshAnimation(HINSTANCE hInstance) {
    if (g_hWnd == NULL) {
        if (!RegisterWindowClass(hInstance)) {
            printf("窗口类注册失败\n");
            return;
        }

        g_hWnd = CreateOverlayWindow(hInstance);
        if (!g_hWnd) return;
    }

    g_fPosX = 0.0f;
    g_animationRunning = true;
}

// 消息处理线程函数
DWORD WINAPI MessageLoopThread(LPVOID lpParam) {
    HINSTANCE hInstance = (HINSTANCE)lpParam;

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

int main(int argc, char* argv[])
{
    // Check driver status.
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK)
    {
        printf("Parsec VDD device is not OK, got status %d.\n", status);
        return 1;
    }

    // Obtain device handle.
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("Failed to obtain the device handle.\n");
        return 1;
    }

    bool running = true;
    std::vector<int> displays;

    // 创建窗口消息处理线程
    HINSTANCE hInstance = GetModuleHandle(NULL);
    HANDLE hMessageThread = CreateThread(
        NULL,
        0,
        MessageLoopThread,
        hInstance,
        0,
        NULL
    );

    // Side thread for updating vdd.
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
        });

    updater.detach();

    // Print out guide.
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a add a virtual display at startup.\n");
    printf("\n");

    printf("Press A to add a virtual display.\n");
    printf("Press R to remove the last added.\n");
    printf("Press Q to quit (then unplug all).\n\n");

    if (running) {
        if (argc == 2 && strcmp(argv[1], "-a") == 0) {
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("Added a new virtual display, index: %d.\n", index);

                // 启动屏幕刷新动画
                StartRefreshAnimation(hInstance);
            }
            else {
                printf("Limit exceeded (%d), could not add more virtual displays.\n", VDD_MAX_DISPLAYS);
            }
        }
    }

    while (running) {
        switch (_getch()) {
            // quit
        case 'q':
            running = false;
            break;
            // add display
        case 'a':
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("Added a new virtual display, index: %d.\n", index);

                // 启动屏幕刷新动画
                StartRefreshAnimation(hInstance);
            }
            else {
                printf("Limit exceeded (%d), could not add more virtual displays.\n", VDD_MAX_DISPLAYS);
            }
            break;
            // remove display
        case 'r':
            if (displays.size() > 0) {
                int index = displays.back();
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("Removed the last virtual display, index: %d.\n", index);
            }
            else {
                printf("No added virtual displays.\n");
            }
            break;
        }
    }

    // Remove all before exiting.
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }

    // 关闭窗口
    if (g_hWnd) {
        PostMessage(g_hWnd, WM_CLOSE, 0, 0);
        WaitForSingleObject(hMessageThread, INFINITE);
        CloseHandle(hMessageThread);
    }

    if (updater.joinable()) {
        updater.join();
    }

    // Close the device handle.
    CloseDeviceHandle(vdd);

    return 0;
}

#endif


#if 0
#include <Windows.h>
#include <d2d1.h>
#include <vector>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <conio.h>
#include "parsec-vdd.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "User32.lib")

using namespace std::chrono_literals;
using namespace parsec_vdd;

// 安全释放宏
#define SafeRelease(p) { if(p) { (p)->Release(); (p) = NULL; } }

// 透明窗口相关全局变量
HANDLE g_hOverlayThread = NULL;
HWND g_hOverlayWnd = NULL;
bool g_bOverlayRunning = false;

// 窗口过程使用的全局变量
struct OverlayData {
    ID2D1Factory* pD2DFactory;
    ID2D1HwndRenderTarget* pRenderTarget;
    ID2D1SolidColorBrush* pBrush;
    RECT targetScreenRect;
    FLOAT fPosX;
};

// 获取所有Parsec虚拟显示器的联合矩形
RECT ComputeParsecDisplaysUnionRect() {
    RECT unionRect = { 0 };
    BOOL first = TRUE;
    DISPLAY_DEVICE displayDevice = { 0 };
    displayDevice.cb = sizeof(DISPLAY_DEVICE);

    for (DWORD devNum = 0; EnumDisplayDevices(NULL, devNum, &displayDevice, 0); devNum++) {
        if (strstr(displayDevice.DeviceString, "Parsec Virtual Display")) {
            DEVMODE devMode = { 0 };
            devMode.dmSize = sizeof(DEVMODE);

            if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
                RECT displayRect;
                displayRect.left = devMode.dmPosition.x;
                displayRect.top = devMode.dmPosition.y;
                displayRect.right = devMode.dmPosition.x + devMode.dmPelsWidth;
                displayRect.bottom = devMode.dmPosition.y + devMode.dmPelsHeight;

                if (first) {
                    unionRect = displayRect;
                    first = FALSE;
                }
                else {
                    UnionRect(&unionRect, &unionRect, &displayRect);
                }
            }
        }
    }
    return unionRect;
}

// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    OverlayData* pData = reinterpret_cast<OverlayData*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

    switch (uMsg) {
    case WM_CREATE: {
        CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
        pData = reinterpret_cast<OverlayData*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pData));

        // 初始化Direct2D
        if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pData->pD2DFactory))) {
            return -1;
        }

        // 创建渲染目标
        D2D1_SIZE_U size = D2D1::SizeU(
            pData->targetScreenRect.right - pData->targetScreenRect.left,
            pData->targetScreenRect.bottom - pData->targetScreenRect.top
        );

        pData->pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &pData->pRenderTarget
        );

        // 创建画刷
        if (pData->pRenderTarget) {
            pData->pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White),
                &pData->pBrush
            );
        }

        // 设置定时器（8ms ≈ 120Hz）
        SetTimer(hWnd, 1, 43, NULL);
        return 0;
    }

    case WM_TIMER: {
        if (!pData || !pData->pRenderTarget) break;

        const FLOAT screenWidth = static_cast<FLOAT>(
            pData->targetScreenRect.right - pData->targetScreenRect.left);
        const FLOAT screenHeight = static_cast<FLOAT>(
            pData->targetScreenRect.bottom - pData->targetScreenRect.top);

        pData->pRenderTarget->BeginDraw();
        pData->pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));  // 完全透明背景

        // 绘制移动白线（1像素高，全屏宽）
        D2D1_RECT_F rect = D2D1::RectF(0.0f, pData->fPosX, screenWidth, pData->fPosX + 1.0f);
        pData->pRenderTarget->FillRectangle(&rect, pData->pBrush);

        // 更新位置
        pData->fPosX += 1.0f;
        if (pData->fPosX > screenHeight) {
            pData->fPosX = 0.0f;
        }

        HRESULT hr = pData->pRenderTarget->EndDraw();
        if (hr == D2DERR_RECREATE_TARGET) {
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pBrush);
        }
        return 0;
    }

    case WM_DESTROY: {
        KillTimer(hWnd, 1);
        if (pData) {
            SafeRelease(pData->pBrush);
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pD2DFactory);
            delete pData;
        }
        PostQuitMessage(0);
        return 0;
    }

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 注册窗口类
BOOL RegisterWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = "ParsecRefreshWindow";
    return RegisterClassEx(&wcex);
}

// 透明窗口线程函数
DWORD WINAPI OverlayThreadProc(LPVOID lpParam) {
    RECT rect = *reinterpret_cast<RECT*>(lpParam);
    HINSTANCE hInstance = GetModuleHandle(NULL);

    // 注册窗口类
    if (!RegisterWindowClass(hInstance)) {
        return 1;
    }

    // 准备窗口数据
    OverlayData* pData = new OverlayData();
    pData->targetScreenRect = rect;
    pData->fPosX = 0.0f;
    pData->pD2DFactory = NULL;
    pData->pRenderTarget = NULL;
    pData->pBrush = NULL;

    // 窗口样式设置
    DWORD dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_NOACTIVATE;
    DWORD dwStyle = WS_POPUP;

    // 创建覆盖整个目标屏幕的窗口
    HWND hWnd = CreateWindowEx(
        dwExStyle,
        "ParsecRefreshWindow",
        "Parsec Refresh Keeper",
        dwStyle,
        rect.left,
        rect.top,
        rect.right - rect.left,
        rect.bottom - rect.top,
        NULL,
        NULL,
        hInstance,
        pData
    );

    if (!hWnd) {
        delete pData;
        return 1;
    }

    // 设置透明属性
    SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
    ShowWindow(hWnd, SW_SHOWNOACTIVATE);
    UpdateWindow(hWnd);

    // 保存窗口句柄
    g_hOverlayWnd = hWnd;

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    g_hOverlayWnd = NULL;
    return 0;
}

// 启动透明窗口
void StartOverlayWindow() {
    if (g_bOverlayRunning) return;

    RECT rect = ComputeParsecDisplaysUnionRect();
    if (IsRectEmpty(&rect)) {
        return;
    }

    g_hOverlayThread = CreateThread(
        NULL,
        0,
        OverlayThreadProc,
        &rect,
        0,
        NULL
    );

    if (g_hOverlayThread) {
        g_bOverlayRunning = true;
    }
}

// 停止透明窗口
void StopOverlayWindow() {
    if (!g_bOverlayRunning) return;

    if (g_hOverlayWnd) {
        PostMessage(g_hOverlayWnd, WM_CLOSE, 0, 0);
    }

    if (g_hOverlayThread) {
        WaitForSingleObject(g_hOverlayThread, INFINITE);
        CloseHandle(g_hOverlayThread);
        g_hOverlayThread = NULL;
    }

    g_hOverlayWnd = NULL;
    g_bOverlayRunning = false;
}

int main(int argc, char* argv[]) {
    // 检查驱动状态
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK) {
        printf("Parsec VDD设备状态异常，状态码：%d\n", status);
        return 1;
    }

    // 获取设备句柄
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("无法获取设备句柄\n");
        return 1;
    }

    bool running = true;
    std::vector<int> displays;

    // 更新线程
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
        });
    updater.detach();

    // 打印指南
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a 启动时自动添加虚拟显示器\n");
    printf("\n");
    printf("按 A 添加虚拟显示器\n");
    printf("按 R 移除最后添加的显示器\n");
    printf("按 Q 退出（并移除所有显示器）\n\n");

    // 启动参数处理
    if (argc == 2 && strcmp(argv[1], "-a") == 0) {
        if (displays.size() < VDD_MAX_DISPLAYS) {
            int index = VddAddDisplay(vdd);
            displays.push_back(index);
            printf("已添加虚拟显示器，索引：%d\n", index);
            StartOverlayWindow(); // 启动透明动画
        }
        else {
            printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
        }
    }

    // 主循环
    while (running) {
        switch (_getch()) {
        case 'q': // 退出
            running = false;
            break;

        case 'a': // 添加显示器
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("已添加虚拟显示器，索引：%d\n", index);
                StartOverlayWindow(); // 启动透明动画
            }
            else {
                printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
            }
            break;

        case 'r': // 移除显示器
            if (!displays.empty()) {
                int index = displays.back();
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("已移除虚拟显示器，索引：%d\n", index);

                // 如果没有显示器了，停止动画
                if (displays.empty()) {
                    StopOverlayWindow();
                }
            }
            else {
                printf("没有可移除的虚拟显示器\n");
            }
            break;
        }
    }

    // 清理资源
    StopOverlayWindow(); // 确保动画停止

    // 移除所有显示器
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }

    // 关闭设备句柄
    CloseDeviceHandle(vdd);

    return 0;
}

#endif



#if 0
#include <Windows.h>
#include <d2d1.h>
#include <vector>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <conio.h>
#include "parsec-vdd.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "User32.lib")

using namespace std::chrono_literals;
using namespace parsec_vdd;

// 安全释放宏
#define SafeRelease(p) { if(p) { (p)->Release(); (p) = NULL; } }

// 透明窗口相关全局变量
HANDLE g_hOverlayThread = NULL;
HWND g_hOverlayWnd = NULL;
bool g_bOverlayRunning = false;

// 窗口过程使用的全局变量
struct OverlayData {
    ID2D1Factory* pD2DFactory;
    ID2D1HwndRenderTarget* pRenderTarget;
    ID2D1SolidColorBrush* pBrush;
    RECT targetScreenRect;
    FLOAT fPosX;
};

// 获取所有Parsec虚拟显示器的联合矩形
RECT ComputeParsecDisplaysUnionRect() {
    RECT unionRect = { 0 };
    BOOL first = TRUE;
    DISPLAY_DEVICE displayDevice = { 0 };
    displayDevice.cb = sizeof(DISPLAY_DEVICE);

    for (DWORD devNum = 0; EnumDisplayDevices(NULL, devNum, &displayDevice, 0); devNum++) {
        if (strstr(displayDevice.DeviceString, "Parsec Virtual Display")) {
            DEVMODE devMode = { 0 };
            devMode.dmSize = sizeof(DEVMODE);

            if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
                RECT displayRect;
                displayRect.left = devMode.dmPosition.x;
                displayRect.top = devMode.dmPosition.y;
                displayRect.right = devMode.dmPosition.x + devMode.dmPelsWidth;
                displayRect.bottom = devMode.dmPosition.y + devMode.dmPelsHeight;

                if (first) {
                    unionRect = displayRect;
                    first = FALSE;
                }
                else {
                    UnionRect(&unionRect, &unionRect, &displayRect);
                }
            }
        }
    }
    return unionRect;
}

// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    OverlayData* pData = reinterpret_cast<OverlayData*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

    switch (uMsg) {
    case WM_CREATE: {
        CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
        pData = reinterpret_cast<OverlayData*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pData));

        // 初始化Direct2D
        if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pData->pD2DFactory))) {
            return -1;
        }

        // 创建渲染目标
        D2D1_SIZE_U size = D2D1::SizeU(
            pData->targetScreenRect.right - pData->targetScreenRect.left,
            pData->targetScreenRect.bottom - pData->targetScreenRect.top
        );

        pData->pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &pData->pRenderTarget
        );

        // 创建画刷
        if (pData->pRenderTarget) {
            pData->pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White),
                &pData->pBrush
            );
        }

        // 设置定时器（16ms ≈ 60Hz） - 降低刷新率以减少GPU使用
        SetTimer(hWnd, 1, 200, NULL);
        return 0;
    }

    case WM_TIMER: {
        if (!pData || !pData->pRenderTarget) break;

        const FLOAT screenWidth = static_cast<FLOAT>(
            pData->targetScreenRect.right - pData->targetScreenRect.left);
        const FLOAT screenHeight = static_cast<FLOAT>(
            pData->targetScreenRect.bottom - pData->targetScreenRect.top);

        pData->pRenderTarget->BeginDraw();
        pData->pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));  // 完全透明背景

        // 绘制移动白线（1像素高，全屏宽）
        D2D1_RECT_F rect = D2D1::RectF(0.0f, pData->fPosX, screenWidth, pData->fPosX + 1.0f);
        pData->pRenderTarget->FillRectangle(&rect, pData->pBrush);

        // 更新位置（每次移动2像素以保持视觉流畅性）
        pData->fPosX += 2.0f;
        if (pData->fPosX > screenHeight) {
            pData->fPosX = 0.0f;
        }

        HRESULT hr = pData->pRenderTarget->EndDraw();
        if (hr == D2DERR_RECREATE_TARGET) {
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pBrush);
        }
        return 0;
    }

    case WM_DISPLAYCHANGE: {
        // 当显示设置更改时重新计算位置
        pData->targetScreenRect = ComputeParsecDisplaysUnionRect();
        if (IsRectEmpty(&pData->targetScreenRect)) {
            DestroyWindow(hWnd);
            return 0;
        }

        // 调整窗口位置和大小
        SetWindowPos(hWnd, HWND_TOPMOST,
            pData->targetScreenRect.left,
            pData->targetScreenRect.top,
            pData->targetScreenRect.right - pData->targetScreenRect.left,
            pData->targetScreenRect.bottom - pData->targetScreenRect.top,
            SWP_NOACTIVATE);

        // 重置渲染目标
        if (pData->pRenderTarget) {
            D2D1_SIZE_U size = D2D1::SizeU(
                pData->targetScreenRect.right - pData->targetScreenRect.left,
                pData->targetScreenRect.bottom - pData->targetScreenRect.top
            );

            pData->pRenderTarget->Resize(size);
        }
        return 0;
    }

    case WM_DESTROY: {
        KillTimer(hWnd, 1);
        if (pData) {
            SafeRelease(pData->pBrush);
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pD2DFactory);
            delete pData;
        }
        PostQuitMessage(0);
        return 0;
    }

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 注册窗口类
BOOL RegisterWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = "ParsecRefreshWindow";
    return RegisterClassEx(&wcex);
}

// 透明窗口线程函数
DWORD WINAPI OverlayThreadProc(LPVOID lpParam) {
    RECT rect = ComputeParsecDisplaysUnionRect();
    if (IsRectEmpty(&rect)) {
        return 1;
    }

    HINSTANCE hInstance = GetModuleHandle(NULL);

    // 注册窗口类
    if (!RegisterWindowClass(hInstance)) {
        return 1;
    }

    // 准备窗口数据
    OverlayData* pData = new OverlayData();
    pData->targetScreenRect = rect;
    pData->fPosX = 0.0f;
    pData->pD2DFactory = NULL;
    pData->pRenderTarget = NULL;
    pData->pBrush = NULL;

    // 窗口样式设置
    DWORD dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_NOACTIVATE;
    DWORD dwStyle = WS_POPUP;

    // 创建覆盖整个目标屏幕的窗口
    HWND hWnd = CreateWindowEx(
        dwExStyle,
        "ParsecRefreshWindow",
        "Parsec Refresh Keeper",
        dwStyle,
        rect.left,
        rect.top,
        rect.right - rect.left,
        rect.bottom - rect.top,
        NULL,
        NULL,
        hInstance,
        pData
    );

    if (!hWnd) {
        delete pData;
        return 1;
    }

    // 设置透明属性
    SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
    ShowWindow(hWnd, SW_SHOWNOACTIVATE);
    UpdateWindow(hWnd);

    // 保存窗口句柄
    g_hOverlayWnd = hWnd;

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    g_hOverlayWnd = NULL;
    return 0;
}

// 启动透明窗口
void StartOverlayWindow() {
    if (g_bOverlayRunning) return;

    g_hOverlayThread = CreateThread(
        NULL,
        0,
        OverlayThreadProc,
        NULL,
        0,
        NULL
    );

    if (g_hOverlayThread) {
        g_bOverlayRunning = true;
    }
}

// 停止透明窗口
void StopOverlayWindow() {
    if (!g_bOverlayRunning) return;

    if (g_hOverlayWnd) {
        PostMessage(g_hOverlayWnd, WM_CLOSE, 0, 0);
    }

    if (g_hOverlayThread) {
        WaitForSingleObject(g_hOverlayThread, INFINITE);
        CloseHandle(g_hOverlayThread);
        g_hOverlayThread = NULL;
    }

    g_hOverlayWnd = NULL;
    g_bOverlayRunning = false;
}

int main(int argc, char* argv[]) {
    // 检查驱动状态
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK) {
        printf("Parsec VDD设备状态异常，状态码：%d\n", status);
        return 1;
    }

    // 获取设备句柄
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("无法获取设备句柄\n");
        return 1;
    }

    bool running = true;
    std::vector<int> displays;

    // 更新线程
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
        });
    updater.detach();

    // 打印指南
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a add a virtual display at startup.\n");
    printf("\n");

    printf("Press A to add a virtual display.\n");
    printf("Press R to remove the last added.\n");
    printf("Press Q to quit (then unplug all).\n\n");


    // 启动参数处理
    if (argc == 2 && strcmp(argv[1], "-a") == 0) {
        if (displays.size() < VDD_MAX_DISPLAYS) {
            int index = VddAddDisplay(vdd);
            displays.push_back(index);
            printf("已添加虚拟显示器，索引：%d\n", index);
            StartOverlayWindow(); // 启动透明动画
        }
        else {
            printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
        }
    }

    // 主循环
    while (running) {
        switch (_getch()) {
        case 'q': // 退出
            running = false;
            break;

        case 'a': // 添加显示器
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("已添加虚拟显示器，索引：%d\n", index);
                StartOverlayWindow(); // 启动透明动画
            }
            else {
                printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
            }
            break;

        case 'r': // 移除显示器
            if (!displays.empty()) {
                int index = displays.back();
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("已移除虚拟显示器，索引：%d\n", index);

                // 如果没有显示器了，停止动画
                if (displays.empty()) {
                    StopOverlayWindow();
                }
            }
            else {
                printf("没有可移除的虚拟显示器\n");
            }
            break;
        }
    }

    // 清理资源
    StopOverlayWindow(); // 确保动画停止

    // 移除所有显示器
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }

    // 关闭设备句柄
    CloseDeviceHandle(vdd);

    return 0;
}
#endif



#if 0
#include <Windows.h>
#include <d2d1.h>
#include <vector>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <conio.h>
#include "parsec-vdd.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "User32.lib")

using namespace std::chrono_literals;
using namespace parsec_vdd;

// 安全释放宏
#define SafeRelease(p) { if(p) { (p)->Release(); (p) = NULL; } }

// 透明窗口相关全局变量
HANDLE g_hOverlayThread = NULL;
HWND g_hOverlayWnd = NULL;
bool g_bOverlayRunning = false;
const int TARGET_FPS = 20; // 目标帧率30FPS

// 窗口过程使用的全局变量
struct OverlayData {
    ID2D1Factory* pD2DFactory;
    ID2D1HwndRenderTarget* pRenderTarget;
    ID2D1SolidColorBrush* pBrush;
    RECT targetScreenRect;
    FLOAT fPosX;
    bool bActive;
    std::chrono::steady_clock::time_point lastFrameTime;
};

// 获取所有Parsec虚拟显示器的联合矩形
RECT ComputeParsecDisplaysUnionRect() {
    RECT unionRect = { 0 };
    BOOL first = TRUE;
    DISPLAY_DEVICE displayDevice = { 0 };
    displayDevice.cb = sizeof(DISPLAY_DEVICE);

    for (DWORD devNum = 0; EnumDisplayDevices(NULL, devNum, &displayDevice, 0); devNum++) {
        if (strstr(displayDevice.DeviceString, "Parsec Virtual Display")) {
            DEVMODE devMode = { 0 };
            devMode.dmSize = sizeof(DEVMODE);

            if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
                RECT displayRect;
                displayRect.left = devMode.dmPosition.x;
                displayRect.top = devMode.dmPosition.y;
                displayRect.right = devMode.dmPosition.x + devMode.dmPelsWidth;
                displayRect.bottom = devMode.dmPosition.y + devMode.dmPelsHeight;

                if (first) {
                    unionRect = displayRect;
                    first = FALSE;
                }
                else {
                    UnionRect(&unionRect, &unionRect, &displayRect);
                }
            }
        }
    }
    return unionRect;
}

// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    OverlayData* pData = reinterpret_cast<OverlayData*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

    switch (uMsg) {
    case WM_CREATE: {
        CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
        pData = reinterpret_cast<OverlayData*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pData));

        // 初始化Direct2D
        if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pData->pD2DFactory))) {
            return -1;
        }

        // 创建渲染目标
        D2D1_SIZE_U size = D2D1::SizeU(
            pData->targetScreenRect.right - pData->targetScreenRect.left,
            pData->targetScreenRect.bottom - pData->targetScreenRect.top
        );

        pData->pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &pData->pRenderTarget
        );

        // 创建画刷
        if (pData->pRenderTarget) {
            pData->pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White),
                &pData->pBrush
            );
        }

        // 初始化动画状态
        pData->bActive = true;
        pData->lastFrameTime = std::chrono::steady_clock::now();

        // 设置低优先级重绘定时器
        SetTimer(hWnd, 1, 1000 / TARGET_FPS, NULL);
        return 0;
    }

    case WM_TIMER: {
        if (!pData || !pData->pRenderTarget || !pData->bActive) break;

        // 计算帧时间
        auto now = std::chrono::steady_clock::now();
        float deltaTime = std::chrono::duration<float>(now - pData->lastFrameTime).count();
        pData->lastFrameTime = now;

        const FLOAT screenWidth = static_cast<FLOAT>(
            pData->targetScreenRect.right - pData->targetScreenRect.left);
        const FLOAT screenHeight = static_cast<FLOAT>(
            pData->targetScreenRect.bottom - pData->targetScreenRect.top);

        pData->pRenderTarget->BeginDraw();
        pData->pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));  // 完全透明背景

        // 绘制移动白线（1像素高，全屏宽）
        D2D1_RECT_F rect = D2D1::RectF(0.0f, pData->fPosX, screenWidth, pData->fPosX + 1.0f);
        pData->pRenderTarget->FillRectangle(&rect, pData->pBrush);

        // 基于时间更新位置（而非固定步长）
        const float SPEED = screenHeight / 2.0f; // 每秒移动半个屏幕高度
        pData->fPosX += SPEED * deltaTime;
        if (pData->fPosX > screenHeight) {
            pData->fPosX = 0.0f;
        }

        HRESULT hr = pData->pRenderTarget->EndDraw();
        if (hr == D2DERR_RECREATE_TARGET) {
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pBrush);
        }
        return 0;
    }

    case WM_DISPLAYCHANGE: {
        // 当显示设置更改时重新计算位置
        RECT newRect = ComputeParsecDisplaysUnionRect();
        if (IsRectEmpty(&newRect)) {
            DestroyWindow(hWnd);
            return 0;
        }

        if (memcmp(&pData->targetScreenRect, &newRect, sizeof(RECT)) != 0) {
            pData->targetScreenRect = newRect;

            // 调整窗口位置和大小
            SetWindowPos(hWnd, HWND_TOPMOST,
                pData->targetScreenRect.left,
                pData->targetScreenRect.top,
                pData->targetScreenRect.right - pData->targetScreenRect.left,
                pData->targetScreenRect.bottom - pData->targetScreenRect.top,
                SWP_NOACTIVATE);

            // 重置渲染目标
            if (pData->pRenderTarget) {
                D2D1_SIZE_U size = D2D1::SizeU(
                    pData->targetScreenRect.right - pData->targetScreenRect.left,
                    pData->targetScreenRect.bottom - pData->targetScreenRect.top
                );

                pData->pRenderTarget->Resize(size);
            }
        }
        return 0;
    }

    case WM_ERASEBKGND:
        return 1; // 阻止背景擦除

    case WM_PAINT: {
        // 最小化绘制处理
        PAINTSTRUCT ps;
        BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        return 0;
    }

    case WM_DESTROY: {
        KillTimer(hWnd, 1);
        if (pData) {
            SafeRelease(pData->pBrush);
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pD2DFactory);
            delete pData;
        }
        PostQuitMessage(0);
        return 0;
    }

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 注册窗口类
BOOL RegisterWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = "ParsecRefreshWindow";
    return RegisterClassEx(&wcex);
}

// 透明窗口线程函数
DWORD WINAPI OverlayThreadProc(LPVOID lpParam) {
    RECT rect = ComputeParsecDisplaysUnionRect();
    if (IsRectEmpty(&rect)) {
        return 1;
    }

    HINSTANCE hInstance = GetModuleHandle(NULL);

    // 注册窗口类
    if (!RegisterWindowClass(hInstance)) {
        return 1;
    }

    // 准备窗口数据
    OverlayData* pData = new OverlayData();
    pData->targetScreenRect = rect;
    pData->fPosX = 0.0f;
    pData->pD2DFactory = NULL;
    pData->pRenderTarget = NULL;
    pData->pBrush = NULL;
    pData->bActive = true;

    // 窗口样式设置
    DWORD dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_NOACTIVATE;
    DWORD dwStyle = WS_POPUP;

    // 创建覆盖整个目标屏幕的窗口
    HWND hWnd = CreateWindowEx(
        dwExStyle,
        "ParsecRefreshWindow",
        "Parsec Refresh Keeper",
        dwStyle,
        rect.left,
        rect.top,
        rect.right - rect.left,
        rect.bottom - rect.top,
        NULL,
        NULL,
        hInstance,
        pData
    );

    if (!hWnd) {
        delete pData;
        return 1;
    }

    // 设置透明属性
    SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
    ShowWindow(hWnd, SW_SHOWNOACTIVATE);
    UpdateWindow(hWnd);

    // 保存窗口句柄
    g_hOverlayWnd = hWnd;

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    g_hOverlayWnd = NULL;
    return 0;
}

// 启动透明窗口
void StartOverlayWindow() {
    if (g_bOverlayRunning) return;

    g_hOverlayThread = CreateThread(
        NULL,
        0,
        OverlayThreadProc,
        NULL,
        0,
        NULL
    );

    if (g_hOverlayThread) {
        g_bOverlayRunning = true;
    }
}

// 停止透明窗口
void StopOverlayWindow() {
    if (!g_bOverlayRunning) return;

    if (g_hOverlayWnd) {
        PostMessage(g_hOverlayWnd, WM_CLOSE, 0, 0);
    }

    if (g_hOverlayThread) {
        WaitForSingleObject(g_hOverlayThread, INFINITE);
        CloseHandle(g_hOverlayThread);
        g_hOverlayThread = NULL;
    }

    g_hOverlayWnd = NULL;
    g_bOverlayRunning = false;
}

int main(int argc, char* argv[]) {
    // 检查驱动状态
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK) {
        printf("Parsec VDD设备状态异常，状态码：%d\n", status);
        return 1;
    }

    // 获取设备句柄
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("无法获取设备句柄\n");
        return 1;
    }

    bool running = true;
    std::vector<int> displays;

    // 更新线程
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
        });
    updater.detach();

    // 打印指南
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a 启动时自动添加虚拟显示器\n");
    printf("\n");
    printf("按 A 添加虚拟显示器\n");
    printf("按 R 移除最后添加的显示器\n");
    printf("按 Q 退出（并移除所有显示器）\n\n");

    // 启动参数处理
    if (argc == 2 && strcmp(argv[1], "-a") == 0) {
        if (displays.size() < VDD_MAX_DISPLAYS) {
            int index = VddAddDisplay(vdd);
            displays.push_back(index);
            printf("已添加虚拟显示器，索引：%d\n", index);
            StartOverlayWindow(); // 启动透明动画
        }
        else {
            printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
        }
    }

    // 主循环
    while (running) {
        switch (_getch()) {
        case 'q': // 退出
            running = false;
            break;

        case 'a': // 添加显示器
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("已添加虚拟显示器，索引：%d\n", index);
                StartOverlayWindow(); // 启动透明动画
            }
            else {
                printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
            }
            break;

        case 'r': // 移除显示器
            if (!displays.empty()) {
                int index = displays.back();
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("已移除虚拟显示器，索引：%d\n", index);

                // 如果没有显示器了，停止动画
                if (displays.empty()) {
                    StopOverlayWindow();
                }
            }
            else {
                printf("没有可移除的虚拟显示器\n");
            }
            break;
        }
    }

    // 清理资源
    StopOverlayWindow(); // 确保动画停止

    // 移除所有显示器
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }

    // 关闭设备句柄
    CloseDeviceHandle(vdd);

    return 0;
}
#endif


#if 0

#include <Windows.h>
#include <d2d1.h>
#include <vector>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <conio.h>
#include "parsec-vdd.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "User32.lib")

using namespace std::chrono_literals;
using namespace parsec_vdd;

// 安全释放宏
#define SafeRelease(p) { if(p) { (p)->Release(); (p) = NULL; } }

// 透明窗口相关全局变量
HANDLE g_hOverlayThread = NULL;
HWND g_hOverlayWnd = NULL;
bool g_bOverlayRunning = false;
const int TARGET_FPS = 10; // 目标帧率30FPS

// 窗口过程使用的全局变量
struct OverlayData {
    ID2D1Factory* pD2DFactory;
    ID2D1HwndRenderTarget* pRenderTarget;
    ID2D1SolidColorBrush* pBrush;
    RECT targetScreenRect;
    FLOAT fPosX;
    bool bActive;
};

// 获取所有Parsec虚拟显示器的联合矩形
RECT ComputeParsecDisplaysUnionRect() {
    RECT unionRect = { 0 };
    BOOL first = TRUE;
    DISPLAY_DEVICE displayDevice = { 0 };
    displayDevice.cb = sizeof(DISPLAY_DEVICE);

    for (DWORD devNum = 0; EnumDisplayDevices(NULL, devNum, &displayDevice, 0); devNum++) {
        if (strstr(displayDevice.DeviceString, "Parsec Virtual Display")) {
            DEVMODE devMode = { 0 };
            devMode.dmSize = sizeof(DEVMODE);

            if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
                RECT displayRect;
                displayRect.left = devMode.dmPosition.x;
                displayRect.top = devMode.dmPosition.y;
                displayRect.right = devMode.dmPosition.x + devMode.dmPelsWidth;
                displayRect.bottom = devMode.dmPosition.y + devMode.dmPelsHeight;

                if (first) {
                    unionRect = displayRect;
                    first = FALSE;
                }
                else {
                    UnionRect(&unionRect, &unionRect, &displayRect);
                }
            }
        }
    }
    return unionRect;
}

// 窗口过程 - 保持初始代码的低GPU占用特性
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    OverlayData* pData = reinterpret_cast<OverlayData*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

    switch (uMsg) {
    case WM_CREATE: {
        CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
        pData = reinterpret_cast<OverlayData*>(pCreate->lpCreateParams);
        SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pData));

        // 初始化Direct2D
        if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pData->pD2DFactory))) {
            return -1;
        }

        // 创建渲染目标
        D2D1_SIZE_U size = D2D1::SizeU(
            pData->targetScreenRect.right - pData->targetScreenRect.left,
            pData->targetScreenRect.bottom - pData->targetScreenRect.top
        );

        pData->pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &pData->pRenderTarget
        );

        // 创建画刷
        if (pData->pRenderTarget) {
            pData->pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White),
                &pData->pBrush
            );
        }

        // 设置定时器（33ms ≈ 30Hz）
        SetTimer(hWnd, 1, 1000 / TARGET_FPS, NULL);
        return 0;
    }

    case WM_TIMER: {
        if (!pData || !pData->pRenderTarget || !pData->bActive) break;

        const FLOAT screenWidth = static_cast<FLOAT>(
            pData->targetScreenRect.right - pData->targetScreenRect.left);
        const FLOAT screenHeight = static_cast<FLOAT>(
            pData->targetScreenRect.bottom - pData->targetScreenRect.top);

        pData->pRenderTarget->BeginDraw();
        pData->pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));  // 完全透明背景

        // 绘制移动白线（1像素高，全屏宽）
        D2D1_RECT_F rect = D2D1::RectF(0.0f, pData->fPosX, screenWidth, pData->fPosX + 1.0f);
        pData->pRenderTarget->FillRectangle(&rect, pData->pBrush);

        // 更新位置
        pData->fPosX += 1.0f;
        if (pData->fPosX > screenHeight) {
            pData->fPosX = 0.0f;
        }

        HRESULT hr = pData->pRenderTarget->EndDraw();
        if (hr == D2DERR_RECREATE_TARGET) {
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pBrush);
        }
        return 0;
    }

    case WM_DISPLAYCHANGE: {
        // 当显示设置更改时重新计算位置
        RECT newRect = ComputeParsecDisplaysUnionRect();
        if (IsRectEmpty(&newRect)) {
            DestroyWindow(hWnd);
            return 0;
        }

        if (memcmp(&pData->targetScreenRect, &newRect, sizeof(RECT)) != 0) {
            pData->targetScreenRect = newRect;

            // 调整窗口位置和大小
            SetWindowPos(hWnd, HWND_TOPMOST,
                pData->targetScreenRect.left,
                pData->targetScreenRect.top,
                pData->targetScreenRect.right - pData->targetScreenRect.left,
                pData->targetScreenRect.bottom - pData->targetScreenRect.top,
                SWP_NOACTIVATE);

            // 重置渲染目标
            if (pData->pRenderTarget) {
                D2D1_SIZE_U size = D2D1::SizeU(
                    pData->targetScreenRect.right - pData->targetScreenRect.left,
                    pData->targetScreenRect.bottom - pData->targetScreenRect.top
                );

                pData->pRenderTarget->Resize(size);
            }
        }
        return 0;
    }

    case WM_ERASEBKGND:
        return 1; // 阻止背景擦除

    case WM_PAINT: {
        // 最小化绘制处理
        PAINTSTRUCT ps;
        BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        return 0;
    }

    case WM_DESTROY: {
        KillTimer(hWnd, 1);
        if (pData) {
            SafeRelease(pData->pBrush);
            SafeRelease(pData->pRenderTarget);
            SafeRelease(pData->pD2DFactory);
            delete pData;
        }
        PostQuitMessage(0);
        return 0;
    }

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 注册窗口类
BOOL RegisterWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = "ParsecRefreshWindow";
    return RegisterClassEx(&wcex);
}

// 透明窗口线程函数
DWORD WINAPI OverlayThreadProc(LPVOID lpParam) {
    // 计算Parsec显示器的联合区域
    RECT rect = ComputeParsecDisplaysUnionRect();
    if (IsRectEmpty(&rect)) {
        return 1; // 没有找到Parsec显示器
    }

    HINSTANCE hInstance = GetModuleHandle(NULL);

    // 注册窗口类
    if (!RegisterWindowClass(hInstance)) {
        return 1;
    }

    // 准备窗口数据
    OverlayData* pData = new OverlayData();
    pData->targetScreenRect = rect;
    pData->fPosX = 0.0f;
    pData->pD2DFactory = NULL;
    pData->pRenderTarget = NULL;
    pData->pBrush = NULL;
    pData->bActive = true;

    // 窗口样式设置
    DWORD dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_NOACTIVATE;
    DWORD dwStyle = WS_POPUP;

    // 创建覆盖整个目标屏幕的窗口
    HWND hWnd = CreateWindowEx(
        dwExStyle,
        "ParsecRefreshWindow",
        "Parsec Refresh Keeper",
        dwStyle,
        rect.left,
        rect.top,
        rect.right - rect.left,
        rect.bottom - rect.top,
        NULL,
        NULL,
        hInstance,
        pData
    );

    if (!hWnd) {
        delete pData;
        return 1;
    }

    // 设置透明属性（完全透明）
    SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
    ShowWindow(hWnd, SW_SHOWNOACTIVATE);
    UpdateWindow(hWnd);

    // 保存窗口句柄
    g_hOverlayWnd = hWnd;

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    g_hOverlayWnd = NULL;
    return 0;
}

// 启动透明窗口
void StartOverlayWindow() {
    if (g_bOverlayRunning) return;

    g_hOverlayThread = CreateThread(
        NULL,
        0,
        OverlayThreadProc,
        NULL,
        0,
        NULL
    );

    if (g_hOverlayThread) {
        g_bOverlayRunning = true;
    }
}

// 停止透明窗口
void StopOverlayWindow() {
    if (!g_bOverlayRunning) return;

    if (g_hOverlayWnd) {
        PostMessage(g_hOverlayWnd, WM_CLOSE, 0, 0);
    }

    if (g_hOverlayThread) {
        WaitForSingleObject(g_hOverlayThread, INFINITE);
        CloseHandle(g_hOverlayThread);
        g_hOverlayThread = NULL;
    }

    g_hOverlayWnd = NULL;
    g_bOverlayRunning = false;
}

int main(int argc, char* argv[]) {
    // 检查驱动状态
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK) {
        printf("Parsec VDD设备状态异常，状态码：%d\n", status);
        return 1;
    }

    // 获取设备句柄
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("无法获取设备句柄\n");
        return 1;
    }

    bool running = true;
    std::vector<int> displays;

    // 更新线程
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
        });
    updater.detach();

    // 打印指南
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a 启动时自动添加虚拟显示器\n");
    printf("\n");
    printf("按 A 添加虚拟显示器\n");
    printf("按 R 移除最后添加的显示器\n");
    printf("按 Q 退出（并移除所有显示器）\n\n");

    // 启动参数处理
    if (argc == 2 && strcmp(argv[1], "-a") == 0) {
        if (displays.size() < VDD_MAX_DISPLAYS) {
            int index = VddAddDisplay(vdd);
            displays.push_back(index);
            printf("已添加虚拟显示器，索引：%d\n", index);
            StartOverlayWindow(); // 启动透明动画
        }
        else {
            printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
        }
    }

    // 主循环
    while (running) {
        switch (_getch()) {
        case 'q': // 退出
            running = false;
            break;

        case 'a': // 添加显示器
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("已添加虚拟显示器，索引：%d\n", index);
                StartOverlayWindow(); // 启动透明动画
            }
            else {
                printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
            }
            break;

        case 'r': // 移除显示器
            if (!displays.empty()) {
                int index = displays.back();
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("已移除虚拟显示器，索引：%d\n", index);

                // 如果没有显示器了，停止动画
                if (displays.empty()) {
                    StopOverlayWindow();
                }
            }
            else {
                printf("没有可移除的虚拟显示器\n");
            }
            break;
        }
    }

    // 清理资源
    StopOverlayWindow(); // 确保动画停止

    // 移除所有显示器
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }

    // 关闭设备句柄
    CloseDeviceHandle(vdd);

    return 0;
}
#endif



#if 1

#include <Windows.h>
#include <d2d1.h>
#include <vector>
#include <thread>
#include <chrono>
#include <stdio.h>
#include <conio.h>
#include "parsec-vdd.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "User32.lib")

using namespace std::chrono_literals;
using namespace parsec_vdd;

// 安全释放宏
#define SafeRelease(p) { if(p) { (p)->Release(); (p) = NULL; } }

// 全局变量
HWND g_hOverlayWnd = NULL;
ID2D1Factory* g_pD2DFactory = NULL;
ID2D1HwndRenderTarget* g_pRenderTarget = NULL;
ID2D1SolidColorBrush* g_pBrush = NULL;
RECT g_targetScreenRect = { 0 };
FLOAT g_fPosX = 0.0f;
bool g_bOverlayRunning = false;
HANDLE g_hOverlayThread = NULL;
HANDLE g_vddHandle = NULL;

// 查找Parsec虚拟显示器
BOOL FindParsecDisplay(RECT& outRect)
{
    DISPLAY_DEVICE displayDevice = { 0 };
    displayDevice.cb = sizeof(DISPLAY_DEVICE);

    // 枚举所有显示器
    for (DWORD devNum = 0; EnumDisplayDevices(NULL, devNum, &displayDevice, 0); devNum++) {
        if (strstr(displayDevice.DeviceString, "Parsec Virtual Display")) {
            DEVMODE devMode = { 0 };
            devMode.dmSize = sizeof(DEVMODE);

            // 获取显示设置
            if (EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
                outRect.left = devMode.dmPosition.x;
                outRect.top = devMode.dmPosition.y;
                outRect.right = devMode.dmPosition.x + devMode.dmPelsWidth;
                outRect.bottom = devMode.dmPosition.y + devMode.dmPelsHeight;
                return TRUE;
            }
        }
    }
    return FALSE;
}

// 窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg) {
    case WM_CREATE: {
        // 初始化Direct2D
        if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory))) {
            return -1;
        }

        // 创建渲染目标
        D2D1_SIZE_U size = D2D1::SizeU(
            g_targetScreenRect.right - g_targetScreenRect.left,
            g_targetScreenRect.bottom - g_targetScreenRect.top
        );

        if (FAILED(g_pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &g_pRenderTarget
        ))) {
            SafeRelease(g_pD2DFactory);
            return -1;
        }

        // 创建画刷
        if (g_pRenderTarget) {
            if (FAILED(g_pRenderTarget->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::White),
                &g_pBrush
            ))) {
                SafeRelease(g_pRenderTarget);
                SafeRelease(g_pD2DFactory);
                return -1;
            }
        }

        // 设置定时器（30Hz刷新率）
        SetTimer(hWnd, 1, 40, NULL);
        return 0;
    }

    case WM_TIMER: {
        if (!g_pRenderTarget) break;

        const FLOAT screenWidth = static_cast<FLOAT>(g_targetScreenRect.right - g_targetScreenRect.left);
        const FLOAT screenHeight = static_cast<FLOAT>(g_targetScreenRect.bottom - g_targetScreenRect.top);

        g_pRenderTarget->BeginDraw();
        g_pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));  // 完全透明背景

        // 绘制移动白线（1像素高，全屏宽）
        D2D1_RECT_F rect = D2D1::RectF(0.0f, g_fPosX, screenWidth, g_fPosX + 1.0f);
        g_pRenderTarget->FillRectangle(&rect, g_pBrush);

        // 更新位置
        g_fPosX += 1.0f;
        if (g_fPosX > screenHeight) {
            g_fPosX = 0.0f;
        }

        HRESULT hr = g_pRenderTarget->EndDraw();
        if (hr == D2DERR_RECREATE_TARGET || FAILED(hr)) {
            SafeRelease(g_pBrush);
            SafeRelease(g_pRenderTarget);
        }
        return 0;
    }

    case WM_DESTROY:
        KillTimer(hWnd, 1);
        SafeRelease(g_pBrush);
        SafeRelease(g_pRenderTarget);
        SafeRelease(g_pD2DFactory);
        g_hOverlayWnd = NULL;
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 注册窗口类
BOOL RegisterWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName = "ParsecRefreshWindow";
    return RegisterClassEx(&wcex);
}

// 创建透明窗口
HWND CreateOverlayWindow(HINSTANCE hInstance) {
    if (!FindParsecDisplay(g_targetScreenRect)) {
        return NULL;
    }

    // 窗口样式设置
    DWORD dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_NOACTIVATE;
    DWORD dwStyle = WS_POPUP;

    // 创建覆盖整个目标屏幕的窗口
    HWND hWnd = CreateWindowEx(
        dwExStyle,
        "ParsecRefreshWindow",
        "Parsec Refresh Keeper",
        dwStyle,
        g_targetScreenRect.left,
        g_targetScreenRect.top,
        g_targetScreenRect.right - g_targetScreenRect.left,
        g_targetScreenRect.bottom - g_targetScreenRect.top,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hWnd) {
        SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
        ShowWindow(hWnd, SW_SHOWNOACTIVATE);
    }
    return hWnd;
}

// 透明窗口线程函数
DWORD WINAPI OverlayThreadProc(LPVOID lpParam) {
    HINSTANCE hInstance = GetModuleHandle(NULL);

    if (!RegisterWindowClass(hInstance)) {
        return 1;
    }

    g_hOverlayWnd = CreateOverlayWindow(hInstance);
    if (!g_hOverlayWnd) {
        return 1;
    }

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

// 启动透明窗口
void StartOverlayWindow() {
    if (g_bOverlayRunning) return;

    g_hOverlayThread = CreateThread(
        NULL,
        0,
        OverlayThreadProc,
        NULL,
        0,
        NULL
    );

    if (g_hOverlayThread) {
        g_bOverlayRunning = true;
    }
}

// 停止透明窗口
void StopOverlayWindow() {
    if (!g_bOverlayRunning) return;

    if (g_hOverlayWnd) {
        PostMessage(g_hOverlayWnd, WM_CLOSE, 0, 0);
        g_hOverlayWnd = NULL;
    }

    if (g_hOverlayThread) {
        // 等待线程结束，最多等待1秒
        WaitForSingleObject(g_hOverlayThread, 1000);
        CloseHandle(g_hOverlayThread);
        g_hOverlayThread = NULL;
    }

    g_bOverlayRunning = false;
}

int main(int argc, char* argv[]) {
    // 检查驱动状态
    DeviceStatus status = QueryDeviceStatus(&VDD_CLASS_GUID, VDD_HARDWARE_ID);
    if (status != DEVICE_OK) {
        printf("Parsec VDD设备状态异常，状态码：%d\n", status);
        return 1;
    }

    // 获取设备句柄
    HANDLE vdd = OpenDeviceHandle(&VDD_ADAPTER_GUID);
    if (vdd == NULL || vdd == INVALID_HANDLE_VALUE) {
        printf("无法获取设备句柄\n");
        return 1;
    }
    g_vddHandle = vdd;

    bool running = true;
    std::vector<int> displays;

    // 更新线程
    std::thread updater([&running, vdd] {
        while (running) {
            VddUpdate(vdd);
            std::this_thread::sleep_for(100ms);
        }
        });
    updater.detach();

    // 打印指南
    printf("parsec-vdd-cli.exe [-a]\n");
    printf("  -a 启动时自动添加虚拟显示器\n");
    printf("\n");
    printf("按 A 添加虚拟显示器\n");
    printf("按 R 移除最后添加的显示器\n");
    printf("按 Q 退出（并移除所有显示器）\n\n");

    // 启动参数处理
    if (argc == 2 && strcmp(argv[1], "-a") == 0) {
        if (displays.size() < VDD_MAX_DISPLAYS) {
            int index = VddAddDisplay(vdd);
            displays.push_back(index);
            printf("已添加虚拟显示器，索引：%d\n", index);
            StartOverlayWindow(); // 启动透明动画
        }
        else {
            printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
        }
    }

    // 主循环
    while (running) {
        switch (_getch()) {
        case 'q': // 退出
            running = false;
            break;

        case 'a': // 添加显示器
            if (displays.size() < VDD_MAX_DISPLAYS) {
                int index = VddAddDisplay(vdd);
                displays.push_back(index);
                printf("已添加虚拟显示器，索引：%d\n", index);
                StartOverlayWindow(); // 启动透明动画
            }
            else {
                printf("已达到最大数量限制 (%d)，无法添加更多显示器\n", VDD_MAX_DISPLAYS);
            }
            break;

        case 'r': // 移除显示器
            if (!displays.empty()) {
                int index = displays.back();
                VddRemoveDisplay(vdd, index);
                displays.pop_back();
                printf("已移除虚拟显示器，索引：%d\n", index);

                // 如果没有显示器了，停止动画
                if (displays.empty()) {
                    StopOverlayWindow();
                }
            }
            else {
                printf("没有可移除的虚拟显示器\n");
            }
            break;
        }
    }

    // 清理资源
    StopOverlayWindow(); // 确保动画停止

    // 移除所有显示器
    for (int index : displays) {
        VddRemoveDisplay(vdd, index);
    }

    // 关闭设备句柄
    CloseDeviceHandle(vdd);
    g_vddHandle = NULL;

    return 0;
}

#endif



